#pragma once

#include "Connection.h"

#include <queue>
#include <mutex>
#include <condition_variable>
#include <memory>
#include <atomic>


class ConnectionPool
{
public:
    /**
     * @brief 获取连接池实例
     * 
     * @return ConnectionPool* 连接池指针
     */
    static ConnectionPool* getConnectionPool();

    /**
     * @brief 从连接池中获取线程
     * 
     * @return std::shared_ptr<Connection> 数据库连接智能指针
     * @note 自定义了数据库连接智能指针的删除器，将连接归还到连接池中
     */
    std::shared_ptr<Connection> getConnection();

private:
    ConnectionPool();
    ~ConnectionPool();

    /**
     * @brief 加载配置文件（包含读取配置文件）
     * 
     * @param name 配置文件名(包含路径)
     * @return true 加载配置文件成功
     * @return false 加载配置文件失败
     */
    bool loadConfigFile(std::string name);

    /**
     * @brief 初始化初始数量的连接添加到连接池中
     * 
     * @return true 成功
     * @return false 失败
     */
    bool initConnection();

    /**
     * @brief 生产者线程函数，负责生产连接放入连接池
     */
    void produceConnection();

    /**
     * @brief 检测空闲连接
     */
    void checkIdleConnection();

    ConnectionPool(const ConnectionPool&) = delete;
    ConnectionPool& operator=(ConnectionPool&) = delete;

private:
    std::atomic<bool> running_;             ///< 当前连接池允许状态

    std::string ip_;                        ///< 数据库IP
    int port_;                              ///< 数据库端口
    std::string password_;                  ///< 数据库密码
    std::string user_;                      ///< 数据库用户名
    std::string dbname_;                    ///< 数据库库名

    const uint32_t initSize_;               ///< 初始数据库连接数量
    const uint32_t maxSize_;                ///< 最大数据库连接数量
    std::atomic<uint32_t> currentSize_;     ///< 记录当前连接中数量(包括线程池中和被用户使用的)
    const uint32_t maxIdleTime_;            ///< 连接最大空闲时间,单位:秒
    const uint32_t connectionTimeout_;      ///< 获取连接超时时间,单位:毫秒

    std::queue<Connection*> connQue_;       ///< 存储连接的连接池
    std::mutex mtx_;                        ///< 保证连接池的线程安全
    std::condition_variable cond_;          ///< 条件变量,进行生产者与消费者线程间通信
};